﻿using CTM.Web.Filters;
using CTM.Web.Models;
using CTM.Web.Models.Input;
using CTM.Web.Models.View.Conversation;
using CTM.Web.Models.View.Home;
using CTM.Web.Services;
using CTM.Web.Utils;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using System;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;

namespace CTM.Web.Controllers
{
    public class ConversationController : Controller
    {
        // initialize service objects
        private IPostService conversationService;
        private INotificationService notificationService;
        private IAccountService accountService; // employee or user service
        private ICategoryService categoryService;
        private ITagService tagService;
        private ApplicationUserManager userManager;
        public ApplicationUserManager UserManager
        {
            get
            {
                return userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                userManager = value;
            }
        }

        public ConversationController(IPostService conversationService, IAccountService accountService, ICategoryService categoryService,
             ITagService tagService, INotificationService notificationService)
        {
            this.conversationService = conversationService;
            this.accountService = accountService;
            this.categoryService = categoryService;
            this.tagService = tagService;
            this.notificationService = notificationService;
        }

        // GET: Conversation
        [ApplicationAuthorize(Permissions = Rights.View + Modules.Conversation)]
        public ActionResult Index(string id)
        {
            id = string.IsNullOrEmpty(id) ? GlobalVariables.CurrentUser.Id : id;
            GlobalVariables.SelectedUser = accountService.GetById(id);

            var conversations = conversationService.SearchConversations(UserManager, null);
            var model = conversations.OrderByDescending(x => x.CreatedOn).GroupBy(c => c.CreatedOn.Year);

            return View(model.ToList());
        }

        [ApplicationAuthorize(Permissions = Rights.View + Modules.Conversation)]
        public ActionResult TimelinePartial(HomeConversationSearchModel searchModel)
        {
            var conversations = conversationService.SearchConversations(UserManager, searchModel);
            var model = conversations.OrderByDescending(x => x.CreatedOn).GroupBy(c => c.CreatedOn.Year);
            return PartialView("_TimelinePartial", model.ToList());
        }

        // GET: Conversation/Details/5
        //public ActionResult Details(Guid? id)
        //{
        //    if (id == null)
        //    {
        //        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        //    }
        //    Post conversation = conversationService.GetById(id);
        //    if (conversation == null)
        //    {
        //        return HttpNotFound();
        //    }
        //    var model = new ConversationViewModel(conversation);
        //    return View(model);
        //}

        // GET: Conversation/Create
        [ApplicationAuthorize(Permissions = Rights.Create + Modules.Conversation)]
        public ActionResult Create()
        {
            var isManager = ApplicationHelpers.IsManager(accountService, UserManager, GlobalVariables.CurrentUser.Id, GlobalVariables.SelectedUser.Id);
            ViewBag.IsManager = isManager;

            var currentUser = accountService.GetById(GlobalVariables.CurrentUser.Id);
            ApplicationUser directManager = null;

            if (isManager == false && currentUser.Manager != null)
                directManager = accountService.GetById(currentUser.Manager.Id);

            var model = new ConversationViewModel();
            if (directManager != null)
            {
                model.Manager = directManager;
                model.ManagerId = directManager.Id;
            }
            else
            {
                directManager = new ApplicationUser();
                model.Manager = directManager;
                model.ManagerId = directManager.Id;
            }

            if (Request.IsAjaxRequest())
                return PartialView(model);
            return View(model);
        }

        // POST: Conversation/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        [ApplicationAuthorize(Permissions = Rights.Create + Modules.Conversation)]
        public ActionResult Create([Bind(Include = "Title,Description,Type,Emoticon,ManagerId")] ConversationViewModel conversation)
        {
            var isManager = ApplicationHelpers.IsManager(accountService, UserManager, GlobalVariables.CurrentUser.Id, GlobalVariables.SelectedUser.Id);
            if (isManager)
                ModelState["ManagerId"].Errors.Clear();

            if (ModelState.IsValid)
            {
                #region Create conversation

                // get 'Conversation' category
                var category = categoryService.GetByName("Conversation");

                var currentUser = accountService.GetById(GlobalVariables.CurrentUser.Id);
                var manager = currentUser;
                var selectedUser = accountService.GetById(GlobalVariables.SelectedUser.Id);

                if (isManager == false)
                    manager = accountService.GetById(conversation.ManagerId);

                var _conversation = new Post
                {
                    Id = Guid.NewGuid(),
                    Title = conversation.Title,
                    Description = conversation.Description,
                    Type = conversation.Type,
                    Emoticon = conversation.Emoticon,
                    IsDeleted = false,
                    CreatedOn = DateTime.UtcNow,
                    CreatedBy = GlobalVariables.CurrentUser.Id,
                    Category = category,
                    Manager = manager,
                    Employee = selectedUser
                };

                // Tags
                var tags = Request.Form["Tags"].Split(',');
                for (int i = 0; i < tags.Length; i++)
                {
                    if (string.IsNullOrWhiteSpace(tags[i])) continue;

                    string tagName = tags[i];
                    var tag = tagService.GetByName(tagName);
                    if (tag != null)
                    {
                        if (!_conversation.Tags.Contains(tag))
                        {
                            _conversation.Tags.Add(tag);
                        }
                    }
                    else
                    {
                        tag = new Tag
                        {
                            Name = tagName
                        };
                        tagService.Insert(tag);
                        _conversation.Tags.Add(tag);
                    }
                }

                conversationService.Insert(_conversation);

                #endregion

                #region Create notification

                notificationService.Create(_conversation, GlobalVariables.CurrentUser.Id);

                #endregion

                return RedirectToAction("Index", new { id = selectedUser.Id });
            }

            if (Request.IsAjaxRequest())
                return PartialView(conversation);
            return View(conversation);
        }

        // GET: Conversation/Edit/5
        [ApplicationAuthorize(Permissions = Rights.Modify + Modules.Conversation)]
        public ActionResult Edit(Guid? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Post conversation = conversationService.GetById(id);
            if (conversation == null)
            {
                return HttpNotFound();
            }
            ViewBag.IsManager = ApplicationHelpers.IsManager(accountService, UserManager, GlobalVariables.CurrentUser.Id, GlobalVariables.SelectedUser.Id);
            var model = new ConversationViewModel(conversation);
            if (Request.IsAjaxRequest())
                return PartialView(model);
            return View(model);
        }

        // POST: Conversation/Edit/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        [ApplicationAuthorize(Permissions = Rights.Modify + Modules.Conversation)]
        public ActionResult Edit([Bind(Include = "Id,Title,Description,Type,Emoticon,ManagerId")] ConversationViewModel conversation)
        {
            var isManager = ApplicationHelpers.IsManager(accountService, UserManager, GlobalVariables.CurrentUser.Id, GlobalVariables.SelectedUser.Id);
            if (isManager)
                ModelState["ManagerId"].Errors.Clear();

            if (ModelState.IsValid)
            {
                var currentUser = accountService.GetById(GlobalVariables.CurrentUser.Id);
                var manager = currentUser;
                var selectedUser = accountService.GetById(GlobalVariables.SelectedUser.Id);

                if (isManager == false)
                    manager = accountService.GetById(conversation.ManagerId);

                Post _conversation = conversationService.GetById(conversation.Id);
                _conversation.Title = conversation.Title;
                _conversation.Description = conversation.Description;
                _conversation.Type = conversation.Type;
                _conversation.Emoticon = conversation.Emoticon;
                _conversation.ModifiedOn = DateTime.UtcNow;
                _conversation.ModifiedBy = GlobalVariables.CurrentUser.Id;

                // Tags
                var tags = Request.Form["Tags"].Split(',');
                for (int i = 0; i < tags.Length; i++)
                {
                    if (string.IsNullOrWhiteSpace(tags[i])) continue;

                    string tagName = tags[i];
                    var tag = tagService.GetByName(tagName);
                    if (tag != null)
                    {
                        if (!_conversation.Tags.Contains(tag))
                        {
                            _conversation.Tags.Add(tag);
                        }
                    }
                    else
                    {
                        tag = new Tag
                        {
                            Name = tagName
                        };
                        tagService.Insert(tag);
                        _conversation.Tags.Add(tag);
                    }
                }

                conversationService.Update(_conversation);
                return RedirectToAction("Index", new { id = selectedUser.Id });
            }
            if (Request.IsAjaxRequest())
                return PartialView(conversation);
            return View(conversation);
        }

        // GET: Conversation/Delete/5
        public ActionResult Delete(Guid? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Post conversation = conversationService.GetById(id);
            if (conversation == null)
            {
                return HttpNotFound();
            }
            var model = new ConversationViewModel(conversation);
            if (Request.IsAjaxRequest())
                return PartialView(model);
            return View(model);
        }

        // POST: Conversation/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(Guid id)
        {
            Post conversation = conversationService.GetById(id);

            // delete comments
            foreach (var comment in conversation.Comments)
            {
                comment.IsDeleted = true;
                comment.ModifiedOn = DateTime.UtcNow;
                comment.ModifiedBy = GlobalVariables.CurrentUser.Id;
            }

            // delete notifications
            foreach (var notification in conversation.Notifications)
            {
                notification.IsDeleted = true;
                //notification.ModifiedOn = DateTime.UtcNow;
                //notification.ModifiedBy = GlobalVariables.CurrentUser.Id;
            }

            conversation.IsDeleted = true;
            conversation.ModifiedOn = DateTime.UtcNow;
            conversation.ModifiedBy = GlobalVariables.CurrentUser.Id;

            conversationService.Update(conversation);
            return RedirectToAction("Index", new { id = GlobalVariables.SelectedUser.Id });
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (userManager != null)
                {
                    userManager.Dispose();
                    userManager = null;
                }
            }

            base.Dispose(disposing);
        }
    }
}